package com.lpy.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.lpy.mapper.*;
import com.lpy.pojo.entity.StockBlockRtInfo;
import com.lpy.pojo.entity.StockMarketIndexInfo;
import com.lpy.pojo.entity.StockOuterMarketIndexInfo;
import com.lpy.pojo.entity.StockRtInfo;
import com.lpy.pojo.vo.StockInfoConfig;
import com.lpy.service.StockTimerTaskService;
import com.lpy.utils.DateTimeUtil;
import com.lpy.utils.IdWorker;
import com.lpy.utils.ParseType;
import com.lpy.utils.ParserStockInfoUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.checkerframework.checker.units.qual.A;
import org.joda.time.DateTime;
import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.fasterxml.jackson.databind.type.LogicalType.Map;

/**
 * @author lpy
 * @date 2025/2/16
 * @Description
 */
@Service("stockTimerTaskService")
@Slf4j
public class StockTimerTaskServiceImpl implements StockTimerTaskService {
    private  HttpEntity<Object> entity;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private StockInfoConfig stockInfoConfig;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private ParserStockInfoUtil parserStockInfoUtil;

    @Autowired
    private StockMarketIndexInfoMapper stockMarketIndexInfoMapper;

    @Autowired
    private StockBusinessMapper stockBusinessMapper;

    @Autowired
    private StockRtInfoMapper stockRtInfoMapper;

    @Autowired
    private StockBlockRtInfoMapper stockBlockRtInfoMapper;

    @Autowired
    private StockOuterMarketIndexInfoMapper stockOuterMarketIndexInfoMapper;

    @Autowired
    RabbitTemplate rabbitTemplate;

    /**
     * 注入线程池对象
     */
    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Override
    public void getInnerMarketInfo() {
        //1.定义采集的url接口
        String url = stockInfoConfig.getMarketUrl()+String.join(",",stockInfoConfig.getInner());
        //2.调用restTemplate采集数据
        //2.1 组装请求头
        HttpHeaders headers = new HttpHeaders();
        //必须填写，否则数据采集不到
//        headers.add("Referer","https://finance.sina.com.cn/stock/");
//        headers.add("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36");
        //2.2 组装请求对象
//        HttpEntity<Object> entity = new HttpEntity<>(headers);
        //2.3 resetTemplate发起请求
        String resString = restTemplate.postForObject(url, entity, String.class);
        //log.info("当前采集的数据：{}",resString);
        //3.数据解析（重要）
//        var hq_str_sh000001="上证指数,3267.8103,3283.4261,3236.6951,3290.2561,3236.4791,0,0,402626660,398081845473,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2022-04-07,15:01:09,00,";
//        var hq_str_sz399001="深证成指,12101.371,12172.911,11972.023,12205.097,11971.334,0.000,0.000,47857870369,524892592190.995,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,2022-04-07,15:00:03,00";
        String reg = "var hq_str_(.+)=\"(.+)\"";
        //编译表达式,获取编译对象
        Pattern pattern = Pattern.compile(reg);
        //匹配字符串
        Matcher matcher = pattern.matcher(resString);
        ArrayList<StockMarketIndexInfo> list = new ArrayList<>();
        //System.out.println(matcher);
        //判断是否有匹配的数值
        while (matcher.find()){
            String marketCode = matcher.group(1);
            String otherInfo = matcher.group(2);

            String[] splitArr = otherInfo.split(",");
            //大盘名称
            String marketName=splitArr[0];
            //获取当前大盘的开盘点数
            BigDecimal openPoint=new BigDecimal(splitArr[1]);
            //前收盘点
            BigDecimal preClosePoint=new BigDecimal(splitArr[2]);
            //获取大盘的当前点数
            BigDecimal curPoint=new BigDecimal(splitArr[3]);
            //获取大盘最高点
            BigDecimal maxPoint=new BigDecimal(splitArr[4]);
            //获取大盘的最低点
            BigDecimal minPoint=new BigDecimal(splitArr[5]);
            //获取成交量
            Long tradeAmt=Long.valueOf(splitArr[8]);
            //获取成交金额
            BigDecimal tradeVol=new BigDecimal(splitArr[9]);
            //时间
            Date curTime = DateTimeUtil.getDateTimeWithoutSecond(splitArr[30] + " " + splitArr[31]).toDate();
            //组装为实体对象
            StockMarketIndexInfo info = StockMarketIndexInfo.builder()
                    .marketName(marketName)
                    .id(idWorker.nextId())
                    .marketCode(marketCode)
                    .openPoint(openPoint)
                    .preClosePoint(preClosePoint)
                    .curPoint(curPoint)
                    .maxPoint(maxPoint)
                    .minPoint(minPoint)
                    .tradeAmount(tradeAmt)
                    .tradeVolume(tradeVol)
                    .curTime(curTime)
                    .build();

            //加入列表
            list.add(info);
        }
        log.info("采集的当前大盘数据：{}",list);
        //批量插入
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        //TODO 后续完成批量插入功能
        //解析的数据批量插入数据库
        int count= stockMarketIndexInfoMapper.insertBatch(list);
        log.info("当前插入了：{}行数据",count);
        if(count>0){
            rabbitTemplate.convertAndSend("stockExchange","inner.market",new Date());
        }else{
            log.error("插入大盘数据失败");
        }

        //通知后台终端刷新本地缓存，发送的日期数据是告知对方当前更新的股票数据所在时间点
        rabbitTemplate.convertAndSend("stockExchange","inner.market",new Date());
    }

    @Override
    public void getStockRtIndex() {
        //1.获取所有股票的id TODO 缓存优化
        List<String> stockIds=stockBusinessMapper.getStockIds();//40--->3000
        //深证：A：以0开头 上证：6开头
        stockIds = stockIds.stream().map(id -> {
            id = id.startsWith("6") ? "sh" + id : "sz" + id;
            return id;
        }).collect(Collectors.toList());
        //要求：将集合分组，每组的集合长度为20
        Lists.partition(stockIds,20).forEach(ids->{
            //每个分片的数据开启一个线程异步执行任务
            threadPoolTaskExecutor.execute(()->{
                //拼接获取A股信息的url地址
                String stockRtUrl=stockInfoConfig.getMarketUrl()+String.join(",",ids);
                //发送请求获取数据
//               String result = restTemplate.getForObject(stockRtUrl, String.class);
                String result=restTemplate.postForObject(stockRtUrl,entity,String.class);
                //解析获取股票数据
                List<StockRtInfo> list = parserStockInfoUtil.parser4StockOrMarketInfo(result, 3);
                //分批次批量插入
                log.info("当前股票数据：{}",list);
                stockRtInfoMapper.insertBatch(list);
            });
        });
    }

    @Override
    public void getStockBlockRtInfo() {
        String stockUrl = "https://vip.stock.finance.sina.com.cn/q/view/newSinaHy.php";
        String result = restTemplate.postForObject(stockUrl, entity, String.class);
        String reg = "var S_Finance_bankuai_sinaindustry = (.+)";
        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(result);
        String infoStr = "";
        HashMap<String, String> map = new HashMap<>();
        if (matcher.find()) {
            infoStr = matcher.group(1);  // 提取 {} 中的内容
            //log.info(infoStr);
        }
        ObjectMapper objectMapper = new ObjectMapper();
        try{
            map = objectMapper.readValue(infoStr, new TypeReference<HashMap<String, String>>() {
            });
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
//        for (Map.Entry<String, String> entry : map.entrySet()) {
//            System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
//        }
        //经测试能够转化为map 类型，接着将其封装进入StockRtInfo对象中
        //列表用来存储每个记录
        //Key: new_blhy, Value: new_blhy,玻璃行业,19,10.328947368421,0.064736842105263,0.63070454312378,349369187,3478405724,sh600552,3.852,13.210,0.490,凯盛科技

        List<StockBlockRtInfo> infos = parserStockInfoUtil.parse4StockBlock(map);
        Lists.partition(infos,15).forEach(list->{
            threadPoolTaskExecutor.execute(()->{
                int count = stockBlockRtInfoMapper.insertBash(infos);
                log.info("【板块】插入数量：{}",count);
            });
        });
    }

    @Override
    public void getOuterMarketInfo() {
        String stockUrl = "http://hq.sinajs.cn/list=int_dji,int_nasdaq,int_hangseng,int_nikkei,b_FSSTI";
        String result = restTemplate.postForObject(stockUrl, entity, String.class);
        System.out.println(result);
        String[] codes = {
                "int_dji","int_nasdaq","int_hangseng"
                ,"int_nikkei","b_FSSTI"
        };
        String[] reg = {
                "var hq_str_int_dji=\"(.+)\"",
                "var hq_str_int_nasdaq=\"(.+)\"",
                "var hq_str_int_hangseng=\"(.+)\"",
                "var hq_str_int_nikkei=\"(.+)\"",
                "var hq_str_b_FSSTI=\"(.+)\""
        };
        String[] res = result.split(";");
        List<StockOuterMarketIndexInfo> list = new ArrayList<>();
        for (int i = 0; i < res.length-1; i++) {
            String currentLine = res[i].trim(); // 去除前后空格
            Pattern pattern = Pattern.compile(reg[i]);
            Matcher matcher = pattern.matcher(currentLine);
            if (matcher.find()) { // 执行匹配操作
                String info = matcher.group(1);
                String[] infos = info.split(",");
                String marketName = infos[0];
                BigDecimal curPoint = new BigDecimal(infos[1]);
                BigDecimal updown = new BigDecimal(infos[2]);
                BigDecimal rose = new BigDecimal(infos[3]);
                Date curTime = DateTimeUtil.getDateTimeWithoutSecond(DateTime.now()).toDate();
                StockOuterMarketIndexInfo stockOuterMarketIndexInfo = StockOuterMarketIndexInfo.builder()
                        .marketCode(codes[i])
                        .id(idWorker.nextId())
                        .marketName(marketName)
                        .curPoint(curPoint)
                        .updown(updown)
                        .rose(rose)
                        .curTime(curTime)
                        .build();
                list.add(stockOuterMarketIndexInfo);
            } else {
                System.err.println("No match found for line: " + currentLine);
            }
        }
        int count = stockOuterMarketIndexInfoMapper.insertBatch(list);

    }


    @PostConstruct
    public void init(){
        HttpHeaders headers = new HttpHeaders();
        headers.add("Referer", "https://finance.sina.com.cn/stock/");
        headers.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36");
        this.entity = new HttpEntity<>(headers);
    }
}

